from geocoder import ip
from geocoder.ipinfo import IpinfoQuery
from requests import get
from typing import Optional
from rich.table import Table
from rich.console import Console
from utils import (
    config,
    WeatherDays,
    Unit, Language, Days,
    get_location,
    format_time
)
from utils.type import _WeatherDays

def weather_days(
        location: Optional[str]=None,
        days: Days=3,
        language: Language=None,
        unit: Unit=None
    ) -> list[_WeatherDays]:
    """
    Get weather forcast for multiple days

    Args:
        location: Location to get weather forcast
        days: Number of days to get weather forcast `(must be >= 3)`
        language: Language to get weather forcast. Default: `None`
        unit: Unit to get weather forcast. Default: `None`

    Raises:
        ValueError: Days must be in 3, 7, 10, 15 or 30

    Returns:
        Weather forcast for multiple days
    """
    # Check days
    if days not in [3, 7, 10, 15, 30]:
        raise ValueError('Days must be in 3, 7, 10, 15 or 30')
    # Get location
    if location is None:
        location = 'me'
        g: IpinfoQuery = ip(location, timeout=1)
        loc = ','.join([str(g.latlng[1]), str(g.latlng[0])])
    else:
        loc = get_location(location)
    # Get language and unit
    if language is None:
        language = config.language
    if unit is None:
        unit = config.unit
    # Get qweather api
    base_url = f'{config.base_url}/v7/weather/{days}d?location={loc}&lang={language}&unit={unit}'
    headers = {'Authorization': f'Bearer {config.token}'}
    # Send request and get response in json format
    resp = get(url=base_url, headers=headers)
    result: WeatherDays = resp.json()
    if 'daily' in result:
        return result['daily']

def print_days(
        table: _WeatherDays,
        days: Days=3,
        unit: Unit=None
    ) -> None:
    """
    Print weather forcast for multiple days with table

    Args:
        table: Weather forcast for multiple days
        days: Number of days to get weather forcast `(must be >= 3)`
        unit: Unit. Defaults to None
    """
    # Check days
    if days not in [3, 7, 10, 15, 30]:
        raise ValueError('Days must be in 3, 7, 10, 15 or 30')
    # Get default unit
    if unit is None:
        unit = config.unit
    # Create Console
    console = Console()
    # Create Table
    t = Table(title=f'🌤️ Weather forcast for {days} days', header_style='bold magenta')
    t.add_column('日期', style='bold cyan', justify='center')
    t.add_column('天气', justify='center')
    t.add_column('温度', justify='center')
    t.add_column('风向风力', justify='center')
    t.add_column('降水量', style='bold blue', justify='center')
    t.add_column('湿度', style='bold blue', justify='center')
    t.add_column('月相', style='bold green', justify='center')
    # Get items
    temp_unit = '°C' if unit == 'm' else '°F'
    # Add rows to table
    for day in table:
        temp_min = f'[bold green]{day['tempMin']}{temp_unit}[/]'
        temp_max = f'[bold yellow]{day['tempMax']}{temp_unit}[/]'
        t.add_row(
            format_time(day['fxDate'], '%Y/%m/%d'),
            day['textDay'] if day['textDay'] == day['textNight'] \
                else f'{day['textDay']}/{day['textNight']}',
            f'{temp_min}~{temp_max}',
            f'{day['windDirDay']} {day['windScaleDay']}级',
            f'{day['precip']}mm',
            f'{day['humidity']}%',
            day['moonPhase']
        )
    # Print table
    console.print(t)
